Remove Montana property tax rebate from non-refundable credit list - #9348
Remove Montana property tax rebate from non-refundable credit list#9348DTrim99 wants to merge 3 commits into
Conversation
The Montana Property Tax Rebate (up to $675 for TY2022-2023) is a standalone rebate claimed on a separate application to the Department of Revenue, not a Form 2 nonrefundable income-tax credit. It was listed in gov.states.mt.tax.income.credits.non_refundable, so it reduced Montana income tax; and because the person-level aggregator mt_non_refundable_credits adds the tax-unit-level $675 rebate, PolicyEngine projected it onto every household member (e.g. $675 x 3 = $2,025 for a family of three), understating MT tax. Remove it from the 2022-01-01 credit list, leaving mt_capital_gain_credit. The rebate variable still computes its $675 value; it simply no longer reduces income tax. Restores mt_income_tax to 5,708.16 for the issue household (was 3,683.16), matching the TaxAct return. Fixes PolicyEngine#9347. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018ECQhxDkVchXm1RNVyqwnx
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018ECQhxDkVchXm1RNVyqwnx
PavelMakarchuk
left a comment
There was a problem hiding this comment.
PR 9348 — Consolidated review report
"Remove Montana property tax rebate from non-refundable credit list" — DTrim99 (fixes #9347; found via TAXSIM discrepancies policyengine-taxsim#1150/#1152)
Source Documents
- Reviewed head SHA:
3066fdce840330ef55ddab14dab4e30046e9fd4f - Mode: full (delegate roles: regulatory [with pdf-collector/audit folded in], references, code-pattern, tests, verification-planner)
- Snapshot:
/tmp/policyengine-command-runs/2b3d452ec8fd/pr9348-pr-snapshot - Role reports:
pr9348-review-context.md,pr9348-review-regulatory.md,pr9348-review-references.md,pr9348-review-code.md,pr9348-review-tests.md,pr9348-review-verification-queue.md(all under RUN_ROOT) - Archived primary sources (Wayback, byte-identical to originals):
pr9348-mt-form2-2022-instructions.pdf(1,403,508 B),pr9348-mt-form2-2023-instructions.pdf(1,412,574 B)
Branch Status
- BEHIND=0, AHEAD=2 — current with
main, no rebase needed. - CI: all 31 checks pass.
- Diff (63 lines, 3 files):
policyengine_us/parameters/gov/states/mt/tax/income/credits/non_refundable.yaml(removesmt_property_tax_rebatefrom the 2022-01-01 list),policyengine_us/tests/policy/baseline/gov/states/mt/tax/income/integration.yaml(1 new case),changelog.d/mt-property-tax-rebate.fixed.md.
Verified substance (why the removal is correct)
The core claim is source-confirmed against both years' primary documents:
- Not a Form 2 credit. The 2023 MT Form 2 Instructions (archived copy, PDF p.5) describe the Property Tax Rebate (HB 222/HB 816, TY2022–2023, lesser of property tax paid or $675) as claimed separately via the TransAction Portal or Form MPTR23 in fixed claim windows, and state the rebate "is exempt from Montana income tax" — it sits entirely outside the income tax calculation. The complete Nonrefundable Credits Schedules for both TY2022 (PDF p.16, pp.43–44) and TY2023 (PDF p.18, pp.46–49) were enumerated line by line: the Property Tax Rebate appears in neither. The 2022 instructions (published Dec 2022, pre-HB 222) never mention it at all.
- Tripling mechanism confirmed in code.
mt_non_refundable_creditsis a Person-entity variable with a parameteraddslist;mt_property_tax_rebateis TaxUnit-entity. policyengine-core projects the tax-unit value onto every member in a Person-leveladds, so a 3-member household carried 3 × $675 = $2,025 of phantom credit (verified in coremap_to/projectsemantics). - Arithmetic re-derived exactly. Issue-9347 household (MT joint, 2023): tax before non-refundable credits $5,708.16; pre-fix $3,683.16 = 5,708.16 − 2,025; post-fix $5,708.16, matching the PR body's TaxAct verification. Both new test assertions (
mt_property_tax_rebate: 675,mt_non_refundable_credits: [0, 0, 0]) were independently hand re-derived, and the case is confirmed discriminating (pre-PR code yields[675, 675, 675]). - No collateral damage.
mt_property_tax_rebateis not orphaned (still consumed viagov.states.household.state_property_tax_credits→taxsim_state_property_tax_credit, plus its own unit test). The remaining list entries —mt_capital_gain_credit(2021/2022) andmt_income_tax_rebate(2021) — are both Person-entity, so no analogous projection defect remains in this list.
Critical
None in this PR's diff. The one-line parameter change is source-confirmed correct for both affected years, the regression test is sound and discriminating, and CI is green.
Disposition note on the references role's C1 (dead 2022 href): the mtrevenue.gov links were dead before this PR (MT DOR site migration; this PR adds no hrefs), the cited content was successfully retrieved and corroborated from archived and live-mirror copies, and verified replacement URLs exist. Per the pre-existing-issue discipline it does not block; it is carried as A1 below because the file is being edited anyway.
Pre-existing findings (outside this diff — follow-up issue material)
The code role's repo-wide entity-projection sweep (6,040 variables AST-parsed; 817 adds lists resolved) found 8 live instances of the same bug class this PR fixes — a Person-entity adds list containing a group-entity variable whose projected value is then summed or subtracted per person. All 8 pre-date this PR, none is touched by its diff, and per canonical rules none blocks it. Recommend opening a tracking issue (one umbrella or eight singles) citing verified core semantics: group→person adds projects the FULL group value onto each member.
| # | Person-entity variable (file) | Offending group-entity entry | Consumer / mechanism |
|---|---|---|---|
| P1 | policyengine_us/variables/gov/states/mt/tax/income/deductions/itemized/general/mt_misc_deductions.py |
casualty_loss_deduction [TaxUnit] |
mt_itemized_deductions_joint.py:24 sums per member (× household size); mt_itemized_deductions_indiv.py:29 doubles on separate-on-same-return. Same MT subsystem as this PR. |
| P2 | policyengine_us/variables/gov/local/ca/la/general_relief/la_general_relief_gross_income.py |
tanf [SPMUnit] |
la_general_relief_net_income.py:16 — TANF counted once per member; exact analogue of #9347 |
| P3 | policyengine_us/variables/gov/states/ms/tax/income/ms_agi_adjustments.py |
self_employed_health_insurance_ald, health_savings_account_ald, self_employed_pension_contribution_ald [TaxUnit] |
ms_agi.py:20 subtracts full unit ALD from each non-dependent → double-counted for couples |
| P4 | policyengine_us/variables/gov/states/oh/tax/income/deductions/medical_exepenses/oh_unreimbursed_medical_care_expense_deduction_person.py |
oh_insured_unreimbursed_medical_care_expenses [TaxUnit] |
oh_unreimbursed_medical_care_expense_deduction.py sums members → × member count |
| P5 | policyengine_us/variables/gov/states/wv/tax/income/subtractions/senior_citizen_disability/wv_senior_citizen_disability_deduction_total_modifications.py |
us_govt_interest [TaxUnit] |
wv_senior_citizen_disability_deduction_person.py:22 — deduction understated for couples |
| P6 | policyengine_us/variables/gov/local/ca/riv/general_relief/income/earned/ca_riv_general_relief_earned_income_deductions.py |
state_withheld_income_tax, additional_medicare_tax [TaxUnit] |
ca_riv_general_relief_net_earned_income.py — deductions double-counted per earner |
| P7 | policyengine_us/variables/gov/local/ca/riv/general_relief/property/ca_riv_general_relief_countable_property_value.py |
spm_unit_cash_assets, ca_riv_general_relief_countable_vehicle_value [SPMUnit] |
ca_riv_general_relief_property_eligible.py:14 auto-sums members → assets × member count → wrongly fails eligibility |
| P8 | policyengine_us/variables/gov/states/il/dhs/aabd/income/expense/il_aabd_expense_exemption_person.py |
state_withheld_income_tax [TaxUnit] |
il_aabd_earned_income_after_exemption_person.py:17 — exemption double-counted for couples |
Additional pre-existing follow-ups (should-address grade, outside this diff):
- P9 — Rebate now reaches household net income through no channel at all (TY2022–2023). After this PR,
mt_property_tax_rebate's only consumer is the TAXSIM reporting aggregate, which feeds nothing inhousehold_net_income. Per the 2023 instructions p.5 the rebate is real money (direct payment, up to $675/yr, income-tax-exempt); faithful modeling is a benefit-side transfer for those historical years. Removing the wrong channel first is correct — track the missing right channel as a follow-up. - P10 — 2024+ leakage into the TAXSIM aggregate.
parameters/gov/states/mt/tax/income/credits/rebate/property/amount.yaml:3-4has no sunset (comment says "only offered in the 2022 and 2023 tax years"), andparameters/gov/states/household/state_property_tax_credits.yamlstill listsmt_property_tax_rebateat 2024/2025/2026 (lines 131, 156, 186) — a phantom $675 MT "property tax credit" in years the program no longer exists. Companion fix: add2024-01-01: 0and drop the 2024+ aggregate entries. - P11 — 2021
mt_income_tax_rebatelikely carries the same misclassification (the 2023 instructions describe the HB 192 income tax rebate as "automatically issued", i.e. another standalone rebate; the 2021 Line-19 list does not name it). This is open PR #8970's territory — flag there rather than expanding this PR.
Should Address
(Actionable within this PR; none blocking.)
- A1 — Refresh the dead
mtrevenue.govhrefs while the file is open (from references C1+S1). 4 of 5 cited hrefs 301→404 after the MT DOR site migration, including the one backing the edited 2022 entry. Verified working replacements atrevenuefiles.mt.govare supplied inpr9348-review-references.md(C1/S1 tables), with page anchors re-verified — note the 2022 anchor corrects#page=17→#page=16("Line 19–Nonrefundable Credits" is on file p.16). While there: the 2025 reference title should name its section ("Schedule III – Tax Credits, Part I – Nonrefundable Credits") and line 10/13 trailing whitespace can be dropped. - A2 — Cite the removal itself in
non_refundable.yaml(references S2). The "not a Form 2 credit" rationale lives only in the PR body and a test comment. Add the verified 2023 What's New citation (.../2023_Montana_Individual_Income_Tax_Return_Form_2_Instructions.pdf#page=5, "claimed via TransAction Portal or Form MPTR23... exempt from Montana income tax"). Do not add an MCA statute cite without verifying the section number (candidate 15-1-2302 unverified). - A3 — TY2022 is the untested half of the change (tests SA-1). The removed entry governed TY2022 and TY2023; only 2023 is tested. Add a
period: 2022sibling case assertingmt_property_tax_rebate: 675andmt_non_refundable_credits: [0, 0, 0]. - A4 — No end-to-end
mt_income_taxassertion (tests SA-2, code SA-1, regulatory suggestion). The headline TaxAct-verified figure (3,683.16 → 5,708.16) is untested; a regression re-booking the rebate downstream ofmt_non_refundable_creditswould pass the new case. Addmt_income_tax: 5_708.16to the issue-9347 case (run the model to confirm reproduction; the neighboring issue-9012 case already follows this pattern). - A5 — Nothing pins that the rebate was rerouted, not dropped (tests SA-3). Add an aggregate test (pattern exists at
tests/.../gov/states/household/state_property_tax_credits/*_in_aggregate.yamlfor vt/pa/nd/in): MT household, 2023, asserttaxsim_state_property_tax_credit: 675.
Suggestions
- S1 — New case uses
state_fips: 30while every other case inintegration.yamlusesstate_code: MT(lines 541, 563); thespm_unitsblock is unnecessary for the asserted outputs. Cosmetic consistency. - S2 — No case covers the 2024-01-01
[]band of the non-refundable list (e.g. 2024 MT filer with capital gains →mt_non_refundable_credits: 0). Cheap guard on the third date band. - S3 — Pre-existing nits in
tests/.../credits/rebate/mt_property_tax_rebate.yaml(untouched here): second case ("676 → 675") is mislabeled "Property tax less than rebate amount"; the exact boundary (675 → 675) is untested. - S4 — Pre-existing:
mt_property_tax_rebate.py:13-19models none of the statutory conditions (principal residence, 7-month ownership and occupancy, taxes billed and paid, claim filing) — worth a comment or follow-up if the rebate gains a benefit-side channel (P9). - S5 — Pre-existing:
ma_mbta_enrolled_in_applicable_programs.pyandtx_dart_reduced_fare_program_eligible.pyuse the Person-adds-group projection intentionally (boolean membership checks, never summed) — semantically correct today but fragile; a clarifying comment would inoculate them against the P1–P8 cleanup.
PDF Audit Summary
- Scope adaptation: pdf-collector and pdf-audit were folded into the regulatory role.
- 2 archived MT DOR Form 2 instruction PDFs (TY2022, TY2023) fetched from the Wayback Machine (captures 2025-04-14 / 2025-05-15, byte-identical to the originals), saved under RUN_ROOT, and quoted verbatim with
#page=cites; the 2025 instructions verified at the liverevenuefiles.mt.govhost. - Key audited facts: $675 lesser-of cap, TY2022/TY2023 only, separate claim (TAP/Form MPTR23), income-tax-exempt, and absence from both years' Nonrefundable Credits Schedules — all corroborated (5/5 references corroborate on content; 4/5 hrefs dead → A1).
- The diff adds no
#page=references (removal-only parameter edit + test + changelog), so the 5E page-anchor check is N/A; existing anchors were re-verified by the references role (one correction: 2022 →#page=16).
Validation Summary
| Role | Result |
|---|---|
| Regulatory (incl. PDF collect/audit) | 0 CRITICAL — removal source-confirmed in both years' primary documents; tripling mechanism and 3,683.16 → 5,708.16 re-derived exactly |
| References | 1 CRITICAL reported (dead 2022 href) — judged pre-existing link rot, content corroborated via archives; carried as A1 with verified replacement URLs |
| Code patterns | 0 CRITICAL in the diff; 8 pre-existing sweep criticals (P1–P8); 9/10 pattern categories clean, 1 N/A |
| Tests | 0 CRITICAL — both asserted values hand re-derived; case confirmed discriminating (pre-PR → [675, 675, 675]) |
| Verification queue | NONE — all cross-role questions settled in-queue; no EXT verification needed |
| Adjacency | Open PR #8970 touches the same MT credit wiring (2021 income tax rebate) — different rebate, no file overlap, no semantic conflict; can merge in either order. P11 flagged to it. |
Review Severity
APPROVE (posting mode: approve-or-request-changes per user instruction).
Judged on THIS diff: zero critical findings; the change is minimal, source-confirmed against primary documents for both affected years, regression-tested with a discriminating case, and CI-green. The 8 sweep criticals are pre-existing and outside the diff — follow-up issue material, not blockers. The should-address items (A1–A5) are non-blocking hardening that would fit naturally in this PR or an immediate follow-up.
Next Steps
- Merge-ready as-is; ideally fold in A1–A5 first (A1/A2 are copy-paste edits from the references report; A3–A5 are three small test cases).
- Open a tracking issue for the entity-projection bug class (P1–P8, file:line list above) — prioritize P1 (
mt_misc_deductions, same MT subsystem) while the team is in this code. - Open follow-ups for P9 (benefit-side channel for the TY2022–2023 rebate) and P10 (2024+ sunset + aggregate leakage).
- Flag P11 (2021 income tax rebate misclassification) on PR #8970 rather than expanding this PR.
Applies the Should-Address and Suggestion items from PavelMakarchuk's 2026-08-27 review. No substantive change to the removal; no parameter value changed. - A1: refresh dead mtrevenue.gov reference hrefs to live revenuefiles.mt.gov URLs (all verified HTTP 200), correct the 2022 anchor #page=17 -> #page=16, name the 2025 reference section, drop trailing whitespace. - A2: cite the removal itself with the 2023 Form 2 What's New (p.5): the property tax rebate is claimed via TAP/Form MPTR23 and is income-tax-exempt, not a Form 2 nonrefundable credit. - A3: add a period 2022 sibling case (the removed entry governed TY2022 too). - A4: assert mt_income_tax 5,708.16 on the issue-9347 case (TaxAct-verified). - A5: add an aggregate test pinning the rebate is rerouted to taxsim_state_property_tax_credit (675), not dropped. - S1: use state_code MT and drop the unneeded spm_units block on the new case. - S2: add a 2024 case covering the empty non-refundable list band. - S3: relabel the mislabeled 676->675 rebate case and add the 675->675 boundary. - S4: note the unmodeled statutory eligibility conditions on the rebate variable. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YCwrSsGY7vPCpKYGfV1xRr
Review addressed — thanks @PavelMakarchukApplied all Should-Address (A1–A5) and Suggestion (S1–S4) items. No change to the substantive removal; no parameter value changed. Should Address
Suggestions
On the pre-existing findings (P1–P11): they're outside this diff, but the 8-instance Person- I couldn't run the suite locally (broken 3.14-alpha venv), so the Fixed with Claude Code assistance. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9348 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 1 1
Lines 35 15 -20
Branches 2 0 -2
=========================================
- Hits 35 15 -20
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Summary
The Montana Property Tax Rebate (up to $675 for TY2022 and TY2023) is a standalone rebate — homeowners claim it on a separate application to the Department of Revenue (tap.dor.mt.gov, window Aug 15 – Oct 1, 2024 for TY2023). It is not a Form 2 nonrefundable income-tax credit and does not reduce income tax liability.
It was listed in
gov.states.mt.tax.income.credits.non_refundable(the2022-01-01entry), somt_income_tax_before_refundable_credits_jointsubtracted it. Two compounding defects:mt_non_refundable_creditsis a Person variable thataddsthe list;mt_property_tax_rebateis a TaxUnit variable ($675), so PolicyEngine projected it onto every member of the tax unit ($675 × 3 = $2,025 for a family of three).Net effect: Montana income tax understated by $675 per household member.
Change
Remove
mt_property_tax_rebatefrom the2022-01-01credit list, leaving[mt_capital_gain_credit]. The rebate variable still computes its $675 value — it simply no longer reduces income tax. (The2024-01-01: []entry already drops it thereafter;mt_income_tax_rebatein the 2021 entry is untouched, as the emulator'ssrebatemechanism relies on it.)Testing
Verified on the issue household (MT joint 2023, ages 26/25, 1 dependent, $114,039 wages, $204 interest, $2,755 property tax):
mt_non_refundable_creditsgoes from[675, 675, 675]→[0, 0, 0]andmt_income_taxfrom 3,683.16 → 5,708.16, matching the TaxAct Form 2 (line 18 = line 20 = $5,708, credit schedule blank). Added a regression test to the Montana integration suite.Found via PolicyEngine-TAXSIM discrepancy #1152 (and its 2022 counterpart #1150), reported by @feenberg.
Sibling of #8970 (@PavelMakarchuk), which scopes the Montana income tax rebate — same subsystem, different rebate, no file overlap.
Fixes #9347.
🤖 Generated with Claude Code